const token = require("../api/service/token");
const logsUtil = require("../tool/logs");
const xml2js = require("xml2js");
const nodeExcel = require("excel-export");
const UUID = require("uuid");
const config = require("../config/config");

const builder = new xml2js.Builder({
  headless: true,
  allowSurrogateChars: true,
  rootName: "xml",
  cdata: true,
});

module.exports = function () {
  return async (ctx, next) => {
    // 合并对象 兼容处理参数
    ctx.get = (id) => {
      let obj = Object.assign({}, ctx.request.query, ctx.request.body);
      if (obj && typeof obj === "string") {
        obj = JSON.parse(obj);
      }

      let value = obj[id] === undefined ? "" : obj[id];
      return value;
    };

    ctx.getQuery = () => {
      return ctx.request.query;
    };

    ctx.getIp = () => {
      let req = ctx.req;
      let ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
      return ip;
    };

    ctx.getBody = () => {
      let obj = Object.assign({}, ctx.body, ctx.request.body);
      if (obj && typeof obj === "string") {
        obj = JSON.parse(obj);
      }
      return obj;
    };

    ctx.getXml = () => {
      let getxml = ctx.request.body;
      return new Promise(async (resolveT, rejectT) => {
        let paramsJson = null;

        const parseObj = await new Promise(function (resolve) {
          xml2js.parseString(getxml, { explicitArray: false }, function (err, json) {
            if (err) throw err;
            return resolve(json);
          });
        });

        if (parseObj.xml) delete parseObj.xml._;
        paramsJson = parseObj.xml;

        console.log("getXml", paramsJson);
        resolveT(paramsJson);
      });
    };

    // 管理后台Api
    ctx.getAdminUserId = () => {
      let adminToken = ctx.header["admin-token"];
      if (adminToken) {
        let userInfo = token.parse(adminToken);
        if (userInfo) {
          return userInfo.id;
        }
      }
      return 0;
    };

    // 获取小程序id
    ctx.getPappletUserId = () => {
      // 模拟用户登陆
      let userId = ctx.request.query["userId206"];
      if (userId) {
        return userId;
      }

      let appletToken = ctx.header["applet-token"];
      if (appletToken) {
        let userInfo = token.parse(appletToken);
        if (userInfo.weixin_openid && userInfo.id) {
          return userInfo.id;
        }
      }
      return 0;
    };

    ctx.getSessionKey = () => {
      let appletToken = ctx.header["applet-token"];
      if (appletToken) {
        let userInfo = token.parse(appletToken);
        if (userInfo.session_key) {
          return userInfo.session_key;
        }
      }

      return "";
    };

    // 获取分页排序
    ctx.getPageSize = () => {
      let pageOption = ctx.get("pageOption");

      if (pageOption && typeof pageOption === "string") {
        pageOption = JSON.parse(pageOption);
      }

      let page = pageOption.page || 1;
      let size = pageOption.pageSize || 20;
      return {
        limit: size,
        offset: size * (page - 1),
      };
    };

    // 获取订单排序相关 [['sale_price','desc']]
    ctx.getOrder = (key) => {
      key = key || "order";
      let order = ctx.get(key);
      if (Array.isArray(order)) {
        return order;
      } else {
        try {
          order = eval("(" + order + ")");
        } catch (e) {
          console.warn("error " + e.message);
          order = [];
        }
        return order;
      }
    };

    //返回自定义code
    ctx.json = (code, message, data) => {
      ctx.response.type = "application/json";
      let resObj = {
        code,
        message,
        data,
      };

      ctx.response.body = resObj;
    };

    ctx.jsonToXml = (return_code, return_msg) => {
      ctx.response.type = "application/xml";
      let resObj = {
        return_code,
        return_msg,
      };

      const xmlOption = builder.buildObject(resObj);
      ctx.response.body = xmlOption;
    };

    ctx.downFile = ({ title, cols, rows }) => {
      let fileName = title + "_" + UUID.v4() + ".xlsx";
      let result = nodeExcel.execute({ cols, rows });
      let data = new Buffer.from(result, "binary");
      ctx.set("Content-Type", "application/vnd.openxmlformats");
      ctx.set("Content-Disposition", "attachment; filename=" + fileName);
      ctx.set("filename", fileName);
      ctx.body = data;
    };

    // 成功请求
    ctx.success = (data) => {
      ctx.json(0, "请求成功！", data);
    };

    // 失败请求
    ctx.fail = (msg) => {
      let message = msg || "请求失败！";
      ctx.json(-1, message, {});
    };

    //token 失效
    ctx.tokenFail = (data) => {
      ctx.json(-2, "非法请求,或登录已超时！", data);
    };

    console.log(`Process API ${ctx.request.method} ${ctx.request.url}...`);

    let allowUrls = config.allowUrls;
    try {
      // 登录注册不需要验证token
      const checkApi = (path) => {
        let isCheck = false;
        for (let i = 0; i < allowUrls.length; i++) {
          let url = allowUrls[i];
          if (path.indexOf(url) > -1) {
            isCheck = true;
          }
        }
        return isCheck;
      };

      if (checkApi(ctx.request.path)) {
        return await next();
      } else {
        if (ctx.request.path.indexOf("/admin_api/") > -1) {
          let id = ctx.getAdminUserId();
          if (id) {
            return await next();
          }
        } else if (ctx.request.path.indexOf("/api/") > -1) {
          return await next();
        }
        return ctx.tokenFail(); // 非法请求
      }
    } catch (e) {
      logsUtil.ctxError(e, ctx);
      return ctx.fail(e.message);
    }
  };
};
